home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / ISSUE01 / TIPTRIX / VARPAR.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1995-06-01  |  3.7 KB  |  110 lines

  1. program VarPar;
  2.  
  3. { A simple program to demonstrate use of type-safe variable number of
  4.   parameters in Delphi.  Written Mars 1995 by Hallvard Vassbotn
  5.   hallvard@falcon.no                                                  }
  6.  
  7. uses WinCrt, SysUtils;
  8.  
  9. { These are predefined in System:
  10. const
  11.     vtInteger  = 0;
  12.     vtBoolean  = 1;
  13.     vtChar     = 2;
  14.     vtExtended = 3;
  15.     vtString   = 4;
  16.     vtPointer  = 5;
  17.     vtPChar    = 6;
  18.     vtObject   = 7;
  19.     vtClass    = 8;
  20.  
  21.   type
  22.     TVarRec = record
  23.       case Integer of
  24.         vtInteger:  (VInteger: Longint; VType: Byte);
  25.         vtBoolean:  (VBoolean: Boolean);
  26.         vtChar:     (VChar: Char);
  27.         vtExtended: (VExtended: PExtended);
  28.         vtString:   (VString: PString);
  29.         vtPointer:  (VPointer: Pointer);
  30.         vtPChar:    (VPChar: PChar);
  31.         vtObject:   (VObject: TObject);
  32.         vtClass:    (VClass: TClass);
  33.     end;
  34. }
  35.  
  36. const
  37.   TypeNames : array [vtInteger..vtClass] of PChar  =
  38.    ('Integer', 'Boolean', 'Char', 'Extended', 'String',
  39.     'Pointer', 'PChar', 'Object', 'Class');
  40.  
  41. {
  42. According to the on-line docs (search for TVarRec), array of const
  43. parameters are treated like array of TVarRec by the compiler.
  44. This example will work just as well if you change the declaration of
  45. TestMultiPar to:
  46.  
  47.   procedure TestMultiPar(const Args: array of TVarRec);
  48.  
  49. This would make the implementation of the routine cleaner (no absolute
  50. variable declaration), but the interface would be less understandable
  51. to the user of the routine.
  52.  
  53. The compiler looks at the parameters and builds the array directly on the
  54. stack. For each item in the array it also sets the VType field to one
  55. of the pre-defined constants vtXXXX. The actual value is always sent as
  56. four bytes of information. For the Boolean and Char types, only the first
  57. byte contains useful information.
  58.  
  59. So, go ahead, now you can write all those neat routines with variable
  60. number of parameters - and still keep the type safety!
  61. }
  62.  
  63. function PtrToHex(P: pointer): string;
  64. begin
  65.   Result := IntToHex(Seg(P^), 4) + ':' + IntToHex(Ofs(P^), 4);
  66. end;
  67.  
  68. procedure TestMultiPar(const Args: array of const);
  69. var
  70.   ArgsTyped : array [0..$fff0 div sizeof(TVarRec)] of TVarRec absolute Args;
  71.   i         : integer;
  72. begin
  73.   for i := Low(Args) to High(Args) do
  74.     with ArgsTyped[i] do
  75.     begin
  76.       Write('Args[', i, '] : ', TypeNames[VType], ' = ');
  77.       case VType of
  78.         vtInteger:  writeln(VInteger);
  79.         vtBoolean:  writeln(VBoolean);
  80.         vtChar:     writeln(VChar);
  81.         vtExtended: writeln(VExtended^:0:4);
  82.         vtString:   writeln(VString^);
  83.         vtPointer:  writeln(PtrToHex(VPointer));
  84.         vtPChar:    writeln(VPChar);
  85.         vtObject:   writeln(PtrToHex(Pointer(VObject)));
  86.         vtClass:    writeln(PtrToHex(Pointer(VClass)));
  87.       end;
  88.     end;
  89. end;
  90.  
  91. var
  92.   MyObj : TObject;
  93. begin
  94.   Writeln('Test of type-safe variable number of parameters in Delphi:');
  95.   MyObj := TObject.Create;
  96.   TestMultiPar([123, 45.67, PChar('ASCIIZ'), 'Hello, world!', true, 'X',
  97.                 @ShortDayNames, TObject, MyObj]);
  98.   MyObj.Free;
  99.  
  100.   { To verify that the type-safety is used in the supplied formatting routines,
  101.     try this: }
  102.   writeln(Format('%d', ['hi']));
  103.   { The supplied parameter is not of the type expected. The '%d' format string
  104.     signals that the parameter should be an integer value, but instead we
  105.     send a string. At run-time this will generate a exception, and if you
  106.     have enabled IDE-trapping of exceptions, Delphi will show you the offending
  107.     line. Using c-type sprintf funtions like this will result in undefined
  108.     behaviour (read: system crash, GP or whatever) }
  109. end.
  110.